package server;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;

import javax.net.ssl.SSLSocket;


/**
 * Thread to fetch images from the camera chip
 * and send it to the client
 */
public class ServerThread extends Thread {

	protected SSLSocket socket;
	protected OutputStream os;
	protected Monitor monitor;
	protected String server;
	protected int port;

	/**
	 * Thread to fetch documents from the document archive
	 * and send it to the client
	 * @param socket The socket the thread sends on
	 * @param monitor The monitor for the shared data in the camera
	 */	
	public ServerThread(SSLSocket socket, Monitor monitor) {
		this.socket = socket;
		this.monitor = monitor;
	}
	
	/**
	 * Initializes socket.
	 * Sends Documents as requested by the client.
	 */
	public void run() {
		if (socket != null) {
			String ans = "";
			
			try {
				os = socket.getOutputStream();
				while(true){
					while (ans.length() == 0){ ans = monitor.getDoc(); }
					sendData(ans.getBytes());
					ans = "";
				}
			} catch (IOException e) {
				System.out.println("Client disconnected...\nKilling readthread...");
				monitor.killThreads();
				monitor.setCommand(5, "");
				System.out.println("Readthread killed... \nKilling serverthread...");
				return;
			} 
		}
	}

	/**
	 * Sends the pertinent data to the client
	 * @param documentData the array with the document data to send
	 * @throws IOException if an I/O error occurs. In particular, an IOException is thrown if the output stream is closed.
	 */
	private synchronized void sendData(byte documentData[]) throws IOException {
 		int bytes = 0;
		int command = monitor.getCommand();
		bytes = documentData.length;
		byte data[] = concat(concat(intToByteArray(command), intToByteArray(bytes)), documentData);
		//os.write(data, 0, bytes + (2*Integer.SIZE));
		os.write(data);
		os.flush();
	}

	/**
	 * Helper method to create the header for the transmission protocol.
	 * Turns Integers into byte arrays.
	 * @param value of the Integer to transform
	 * @return the array
	 */
	private final byte[] intToByteArray(int value) {
		return new byte[] { (byte) (value >>> 24), (byte) (value >>> 16),
				(byte) (value >>> 8), (byte) value };
	}

	/**
	 * Helper method to create the header for the transmission protocol.
	 * Concatenates the arrays into a new array of appropriate size.
	 * @param first array
	 * @param second array
	 * @return finished array
	 */
	private byte[] concat(byte[] first, byte[] second) {
		byte[] result = Arrays.copyOf(first, first.length + second.length);
		System.arraycopy(second, 0, result, first.length, second.length);
		return result;
	}
}